package yartiss.gui.view;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.LayoutManager;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.File;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.swing.BorderFactory;
import javax.swing.BoundedRangeModel;
import javax.swing.BoxLayout;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.filechooser.FileFilter;

import net.miginfocom.swing.MigLayout;
import yartiss.framework.view.AbstractView;
import yartiss.framework.viewmodel.AbstractViewModel;
import yartiss.service.viewmodel.TaskSetsGenViewModel;

@SuppressWarnings("serial")
public class TasksetsGeneratorView extends AbstractView{

	private AbstractViewModel viewModel;
	public JTextField selectedConsumptionProfileField = new JTextField();
	public JTextField selectedTaskTypeField = new JTextField();
	public ActionListener generateCommand = null;
	public JTextField EminField;
	public JTextField PrField;
	public JTextField EmaxField;
	private JComboBox<String> availibaleConsumptionProfiles;
	private JCheckBox isGlobalConsupltionCheckBox;
	private JCheckBox isVariateU;;
	public JTextField utilizationField;
	public JTextField energyUtilizationField;
	public JTextField countField;
	public JTextField nbTasksField;
	private JButton generate;
	public JTextField systemsFileField;
	private BoundedRangeModel globalProgressModel;
	public JTextField nbProcField;

	public TasksetsGeneratorView(){
		setResizeWeight(1.0);
		setOneTouchExpandable(true);
		setLeftComponent(buildLeftComponent());
		setRightComponent(buildContent());
		registerGUIListerners();
		initializeGUI();
	}

	private void initializeGUI() {
		// TODO Auto-generated method stub
	}

	private void registerGUIListerners(){
		isGlobalConsupltionCheckBox.addActionListener(new ActionListener() {
			@Override public void actionPerformed(ActionEvent e) {
				viewModel.setProperty("IsGlobalConsumption", isGlobalConsupltionCheckBox.isSelected());
				generate.setEnabled(true);
				availibaleConsumptionProfiles.setEnabled(isGlobalConsupltionCheckBox.isSelected());
			}
		});
		isVariateU.addActionListener(new ActionListener() {
			@Override public void actionPerformed(ActionEvent e) {
				viewModel.setProperty("VariateU", isVariateU.isSelected());
				generate.setEnabled(true);
			}
		});
		browseFileButton.addActionListener( new ActionListener() {
			@Override	public void actionPerformed(ActionEvent e) {
				JFileChooser fileChooser = new JFileChooser(systemsFileField.getText());
				fileChooser.setFileFilter(new FileFilter() {
					@Override
					public String getDescription() {
						return "RTSS";
					}

					@Override
					public boolean accept(File f) {
						return true;
					}
				});
				int result = fileChooser.showSaveDialog(browseFileButton);
				if (result == JFileChooser.APPROVE_OPTION) {
					File file = fileChooser.getSelectedFile();
					viewModel.setProperty("SystemsFile",file.getPath());
					setProperty("SystemsFile",file.getPath());
					generate.setEnabled(true);
				}
			}
		});

		availibaleConsumptionProfiles.addActionListener(new MyActionListerner(null, "SelectedConsumptionProfile"));
		availibaleTaskTypes.addActionListener(new MyActionListerner(null, "SelectedTaskType"));
		addListeners(EminField,"Emin");
		addListeners(PrField,"Pr");
		addListeners(EmaxField,"Emax");
		addListeners(countField,"Count");
		addListeners(nbTasksField,"NbTasks");
		addListeners(utilizationField,"Utilization");
		addListeners(energyUtilizationField,"EnergyUtilization");
		addListeners(nbProcField,"NbProc");
	}

	public class MyActionListerner implements ActionListener, FocusListener, KeyListener{

		private final String propName;
		String oldValue;
		private final JTextField source;
		private boolean valide;
		public MyActionListerner(JTextField source, String propName){
			this.source = source;
			this.propName = propName;
		}
		@Override public void actionPerformed(ActionEvent e) {doIt(e.getSource());}
		@Override public void focusGained(FocusEvent e) {oldValue = source != null ? source.getText() : "";}
		@Override public void focusLost(FocusEvent e) {doIt(e.getSource());}
		private void doIt(Object source){
			Object value = null;
			if(source == availibaleConsumptionProfiles){
				setProperty(propName,availibaleConsumptionProfiles.getSelectedItem().toString());
				value = getProperty(propName);
				fireGuiPropertyChanged(propName, value, value);
			}
			else if(source == availibaleTaskTypes){
				setProperty(propName,availibaleTaskTypes.getSelectedItem().toString());
				value = getProperty(propName);
				fireGuiPropertyChanged(propName, value, value);
			}
			if(this.source != null && !valide){
				this.source.setText(oldValue);
				this.source.setForeground(Color.BLACK);
			}
			value = getProperty(propName);
			fireGuiPropertyChanged(propName, value, value);
		}
		@Override
		public void keyTyped(KeyEvent e) {
			String input = source.getText();
			Pattern p = Pattern.compile("[A-Z,a-z,&%$#@!()*^]");
			Matcher m = p.matcher(input);
			if (m.find()){
				source.setForeground(Color.RED);
				valide = false;
			}
			else {
				source.setForeground(Color.black);
				valide = true;
			}
		}
		@Override public void keyPressed(KeyEvent e) {}
		@Override public void keyReleased(KeyEvent e) {}
	}


	private void addListeners(JTextField f, String prop){
		MyActionListerner l = new MyActionListerner(f, prop);
		f.addActionListener(l);
		f.addFocusListener(l);
		f.addKeyListener(l);
	}

	@Override
	public AbstractViewModel getDataContext() {
		return viewModel;
	}


	@Override
	public void setDataContext(AbstractViewModel viewModel) {
		unSuscribeListeners();
		this.viewModel = viewModel;
		suscribeListeners();
		fireViewModelChanged(viewModel);
	}

	private void fireViewModelChanged(AbstractViewModel vm){
		for (String propName : propertiesNames) {
			setProperty(propName);
		}
		setProperty("AvailibaleConsumptionProfiles");
		setProperty("SelectedConsumptionProfile");
		setProperty("SelectedTaskType");
		setProperty("AvailibaleTaskTypes");
		setProperty("GenerateCommand");
		setProperty("IsContentChanged");
		setProperty("IsGlobalConsumption");
		setProperty("GenerateCommand");
		setProperty("VariateU");
		setProperty("GlobalProgressModel");
	}

	private void setProperty(String propName){
		Object value = viewModel.getProperty(propName);
		if("SelectedConsumptionProfile".equals(propName) ){
			selectedConsumptionProfileField.setText(value.toString());
			availibaleConsumptionProfiles.setSelectedItem(value+"");
		}
		else if("AvailibaleConsumptionProfiles".equals(propName) ){
			String [] profiles = viewModel.getProperty(propName);
			availibaleConsumptionProfiles.setModel(new DefaultComboBoxModel<String>(profiles));
			selectedConsumptionProfileField.setText(profiles[0]);
		}
		else if("SelectedTaskType".equals(propName) ){
			System.out.println("toto");
			selectedTaskTypeField.setText(value.toString());
			availibaleTaskTypes.setSelectedItem(value+"");
		}
		else if("AvailibaleTaskTypes".equals(propName) ){
			String [] types = viewModel.getProperty(propName);
			availibaleTaskTypes.setModel(new DefaultComboBoxModel<String>(types));
			availibaleTaskTypes.setSelectedItem(selectedTaskTypeField.getText());
		}
		else if ("GenerateCommand".equals(propName) ){ 
			generate.removeActionListener(generateCommand);
			generateCommand = viewModel.getProperty(propName);
			generate.addActionListener(generateCommand);
		}
		else if ("IsContentChanged" .equals(propName) ){
			Boolean enabled = viewModel.getProperty(propName);
			generate.setEnabled(enabled);
		}
		else if ("IsGlobalConsumption".equals(propName) ){
			boolean selected = viewModel.getProperty(propName);
			isGlobalConsupltionCheckBox.setSelected(selected);
			availibaleConsumptionProfiles.setEnabled(selected);
		}
		else if ("VariateU" .equals(propName) ){
			boolean val = viewModel.getProperty(propName);
			isVariateU.setSelected(val);
		}
		else if ("GlobalProgressModel" .equals(propName) ){
			globalProgressModel = viewModel.getProperty(propName);
			globalProgressBar.setModel(globalProgressModel);
		}	
		else {
			setProperty(propName, value);
		}
	}

	private PropertyChangeListener listener = new PropertyChangeListener() {
		@Override  public void propertyChange(PropertyChangeEvent evt) {
			setProperty(evt.getPropertyName());
		}
	};

	private void suscribeListeners() {
		if(viewModel != null)
			viewModel.registerPropertyChangeListerner(listener);
	}

	private void unSuscribeListeners() {
		if(viewModel != null)
			viewModel.unregisterPropertyChangeListener(listener);
	}

	private JProgressBar globalProgressBar;
	private JButton browseFileButton;
	private JComboBox<String> availibaleTaskTypes;


	public JComponent buildLeftComponent(){
		JPanel panel =new JPanel(new BorderLayout());
		globalProgressBar = new JProgressBar();
		panel.add(globalProgressBar, BorderLayout.CENTER);
		return panel;
	}


	private JComponent buildContent(){

		JPanel simulationPane = new JPanel();
		BoxLayout b = new BoxLayout(simulationPane, BoxLayout.Y_AXIS);
		simulationPane.setLayout(b);
		simulationPane.setBorder(BorderFactory.createTitledBorder("Simulation"));

		generate = new JButton("Go");
		systemsFileField = new JTextField(15); 
		systemsFileField.setMinimumSize(new Dimension(80,10));
		browseFileButton = new JButton("brose");

		JPanel p = new JPanel(new MigLayout());
		p.add(generate, "span, growx, wrap para");
		p.add(new JLabel("Systems file"), "gap para");p.add(systemsFileField    ,  "gap para");
		p.add(browseFileButton    ,   "span, growx, wrap para");
		simulationPane.add(p);


		JPanel energyProfilePane = new JPanel(new MigLayout());
		energyProfilePane.setBorder(BorderFactory.createTitledBorder("Energy profile"));

		utilizationField = new JTextField(15);
		energyUtilizationField = new JTextField(15);
		countField = new JTextField(15);
		nbTasksField = new JTextField(15);
		isVariateU = new JCheckBox("Utilizations variation");

		nbProcField = new JTextField(15);
		availibaleTaskTypes = new JComboBox<String>();

		JPanel systemPane = new JPanel(new MigLayout());
		systemPane.setBorder(BorderFactory.createTitledBorder("System"));

		systemPane.add(new JLabel("nb Tasks"), "gap 10");systemPane.add(nbTasksField    , "gap para");	
		systemPane.add(new JLabel("Count"), "gap 10");systemPane.add(countField    , "span, growx, wrap para");
		systemPane.add(new JLabel("Time U"), "gap 10");systemPane.add(utilizationField    , "gap para");	
		systemPane.add(new JLabel("Energy U"), "gap 10");systemPane.add(energyUtilizationField    , "span, growx, wrap para");

		systemPane.add(new JLabel("nb Proc"), "gap 10");systemPane.add(nbProcField    , "gap para");	
		systemPane.add(new JLabel("Tasks type"), "gap 10");systemPane.add(availibaleTaskTypes    , "span, growx, wrap para");

		systemPane.add(isVariateU    , "span, growx, wrap para");


		EminField = new JTextField(15);
		PrField 	= new JTextField(15);
		EmaxField = new JTextField(15);
		availibaleConsumptionProfiles = new JComboBox<String>();
		availibaleConsumptionProfiles.setMaximumSize(new Dimension(110,50));
		isGlobalConsupltionCheckBox = new JCheckBox("Global"); 

		energyProfilePane.add(new JLabel("Emax"), "gap 10");energyProfilePane.add(EmaxField    , "gap 10");
		energyProfilePane.add(new JLabel("Pr"), "gap 10");	energyProfilePane.add(PrField    , "span, growx, wrap para");
		energyProfilePane.add(new JLabel("Consuption"), "gap 10");energyProfilePane.add(availibaleConsumptionProfiles    , "gap 10");
		energyProfilePane.add(isGlobalConsupltionCheckBox);	

		JPanel rightPane = new JPanel();
		BoxLayout layout = new BoxLayout(rightPane, BoxLayout.Y_AXIS);
		rightPane.setLayout(layout);
		rightPane.add(simulationPane);
		rightPane.add(energyProfilePane);
		rightPane.add(systemPane);

		JPanel pp = new JPanel(new LayoutManager() {
			int width=400;
			//int height=800;
			@Override public void removeLayoutComponent(Component comp) {}

			@Override public Dimension preferredLayoutSize(Container parent) {
				return new Dimension(width,parent.getHeight());
			}

			@Override public Dimension minimumLayoutSize(Container parent) {
				return new Dimension(width,parent.getHeight());
			}

			@Override public void layoutContainer(Container parent) {
				for (Component comp : parent.getComponents()) {
					comp.setSize(width, parent.getHeight());
				}
			}
			@Override public void addLayoutComponent(String name, Component comp) {}
		});

		pp.add(rightPane);

		JScrollPane Scroll = new JScrollPane(pp);
		Scroll.setMinimumSize(new Dimension(410,0));
		Scroll.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
		return Scroll;

	}


	public static void main(String[] args) {

		JFrame window = new JFrame("RTSS-");
		Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
		Dimension d = new Dimension(screenSize);
		d.width  *= (5.0 / 6.0);
		d.height *= (5.0 / 6.0);
		window.setBounds((screenSize.width - d.width) / 2, (screenSize.height - d.height) / 2, d.width, d.height);
		window.setPreferredSize(d);
		window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

		TaskSetsGenViewModel vm = new TaskSetsGenViewModel();
		TasksetsGeneratorView view = new TasksetsGeneratorView();

		vm.setView(view);
		JComponent root = (JComponent) vm.getView();

		window.setContentPane(root);
		window.setVisible(true);
	}


}
